/*
 * ShellListView.java
 *
 * Created on April 20, 2002, 11:29 PM
 */

package fr.umlv.cmis.listview;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.MouseInputAdapter;
import javax.swing.filechooser.FileSystemView;

import org.apache.chemistry.opencmis.client.api.CmisObject;

import fr.umlv.dnd.CustomDropTargetListener;

// TODO: Auto-generated Javadoc
/**
 * The Class CmisObjectListView.
 */
public class CmisObjectListView extends JComponent implements ViewComponent {
   
	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;

	/** The Constant ICON_SIZE. */
	private static final int ICON_SIZE = 24;
	
	/** The Constant VS_DETAIL. */
    public static final int VS_DETAIL = 0;
    
    /** The Constant VS_LIST. */
    public static final int VS_LIST = 1;
    
    /** The Constant VS_ICON. */
    public static final int VS_ICON = 2;
    
    /** The Constant VS_THUMBNAIL. */
    public static final int VS_THUMBNAIL = 3;
    
    /** The data model. */
    protected CmisObjectListViewModel dataModel;
    
    /** The selection model. */
    protected CmisObjectListViewSelectionModel selectionModel;
    
    /** The scroll pane. */
    protected JScrollPane scrollPane;
    
    /** The detail view. */
    protected DetailView detailView;
    
    /** The list view. */
    protected ListView listView;
    
    /** The icon view. */
    protected CmisIconView iconView;
    
    /** The thumbnail view. */
    protected CmisThumbnailView thumbnailView;
    
    /** The view style. */
    protected int viewStyle;
    
    /**
     * Instantiates a new cmis object list view.
     */
    public CmisObjectListView() {
        this(FileSystemView.getFileSystemView().getHomeDirectory(),FileSystemView.getFileSystemView(),true,VS_DETAIL,true);

    }
    
    /**
     * Instantiates a new cmis object list view.
     *
     * @param dir the dir
     * @param fsv the fsv
     * @param useFileHiding the use file hiding
     * @param viewStyle the view style
     * @param thumbnailEnabled the thumbnail enabled
     */
    public CmisObjectListView(File dir, FileSystemView fsv, boolean useFileHiding, int viewStyle, boolean thumbnailEnabled) {
        ViewMouseHandler viewMouseHandler = new ViewMouseHandler();
        ViewKeyHandler viewKeyHandler = new ViewKeyHandler();
        
        dataModel = new CmisObjectListViewModel(false,1);
        selectionModel = new CmisObjectListViewSelectionModel(dataModel);
        
        detailView = new DetailView(dataModel);
        detailView.setSelectionModel(selectionModel);
        detailView.addMouseListener(viewMouseHandler);
        detailView.addKeyListener(viewKeyHandler);
        
        listView = new ListView(dataModel);
        listView.setSelectionModel(selectionModel);
        listView.addMouseListener(viewMouseHandler);
        listView.addKeyListener(viewKeyHandler);
        
        iconView = new CmisIconView(dataModel);
        iconView.setSelectionModel(selectionModel);
        iconView.addMouseListener(viewMouseHandler);
        iconView.addKeyListener(viewKeyHandler);
        
        thumbnailView = new CmisThumbnailView(dataModel);
        thumbnailView.setSelectionModel(selectionModel);
        thumbnailView.setEnabled(thumbnailEnabled);
        thumbnailView.addMouseListener(viewMouseHandler);
        thumbnailView.addKeyListener(viewKeyHandler);
        
        dataModel.addListDataListener(new javax.swing.event.ListDataListener() {
            public void contentsChanged(ListDataEvent evt) { onContentsChanged(evt); }
            public void intervalAdded(ListDataEvent evt) { /* do nothing */ }
            public void intervalRemoved(ListDataEvent evt) { /* do nothing */ }
        });
        
        scrollPane = new JScrollPane();
        
        setFileHidingEnabled(useFileHiding);
        setViewStyle(viewStyle);
        
        setBackground(UIManager.getColor("List.background"));
        setForeground(UIManager.getColor("List.foreground"));
        setFont(UIManager.getFont("Table.font"));
        scrollPane.getViewport().setBackground(getBackground());
        
        setLayout(new BorderLayout());
        add(scrollPane,BorderLayout.CENTER);
        
        new CustomDropTargetListener(this);
        
        refresh();
        
        //updateUI();
    }
    
    /**
     * Gets the model.
     *
     * @return the model
     */
    /*public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //scrollPane.getViewport().setBackground(getBackground());
    }*/
    
    
    
    /** Returns the <code>ShellListViewModel</code> that provides the data displayed by this component.
     * @return the <code>ShellListViewModel</code> that provides the data displayed by this component.
     */
    public CmisObjectListViewModel getModel() {
        return dataModel;
    }
    
    /**
     * Gets the last selected index.
     *
     * @return the last selected index
     */
    public int getLastSelectedIndex() {
        return selectionModel.getLastSelectedIndex();
    }
    
    /**
     * Gets the last selected file.
     *
     * @return the last selected file
     */
    public CmisObject getLastSelectedFile() {
        return selectionModel.getLastSelectedFile();
    }
    
    /**
     * Gets the selected files.
     *
     * @return the selected files
     */
    public List<CmisObject> getSelectedFiles() {
        return selectionModel.getSelectedFiles();
    }
    
    /**
     * Gets the all files.
     *
     * @return the all files
     */
    public List<CmisObject> getAllFiles() {
        return selectionModel.getAllFiles();
    }
    
    /**
     * Refresh.
     */
    public void refresh() {
        dataModel.refresh();
    }
    
    /**
     * Gets the view style.
     *
     * @return the view style
     */
    public int getViewStyle() {
        return this.viewStyle;
    }
    
    /**
     * Sets the view style.
     *
     * @param viewStyle the new view style
     */
    public void setViewStyle(int viewStyle) {
        if (viewStyle == VS_DETAIL) {
            scrollPane.setViewportView(detailView);
            this.viewStyle = viewStyle;
        } else if (viewStyle == VS_LIST) {
            scrollPane.setViewportView(listView);
            this.viewStyle = viewStyle;
        } else if (viewStyle == VS_ICON) {
            scrollPane.setViewportView(iconView);
            this.viewStyle = viewStyle;
        } else if (viewStyle == VS_THUMBNAIL) {
            scrollPane.setViewportView(thumbnailView);
            this.viewStyle = viewStyle;
        } else {
            throw new IllegalArgumentException("Illegal viewStyle");
        }
        
        revalidate();
    }
    
    /**
     * Sets the current directory.
     *
     * @param dir the new current directory
     */
    public void setCurrentDirectory(CmisObject dir) {
        dataModel.setCurrentDirectory(dir);
    }
    
    /**
     * Gets the current directory.
     *
     * @return the current directory
     */
    public CmisObject getCurrentDirectory() {
        return dataModel.getCurrentDirectory();
    }
    
    /**
     * Sets the file hiding enabled.
     *
     * @param useFileHiding the new file hiding enabled
     */
    public void setFileHidingEnabled(boolean useFileHiding) {
        dataModel.setFileHidingEnabled(useFileHiding);
    }
    
    /**
     * Checks if is file hiding enabled.
     *
     * @return true, if is file hiding enabled
     */
    public boolean isFileHidingEnabled() {
        return dataModel.isFileHidingEnabled();
    }
    
    /**
     * Gets the view component.
     *
     * @return the view component
     */
    public ViewComponent getViewComponent() {
        Component comp = scrollPane.getViewport().getView();
        if (comp == null) { return null; }
        return (ViewComponent)comp;
    }
    
    /**
     * Gets the detail view.
     *
     * @return the detail view
     */
    public DetailView getDetailView() {
        return detailView;
    }
    
    /**
     * Gets the list view.
     *
     * @return the list view
     */
    public ListView getListView() {
        return listView;
    }
    
    /**
     * Gets the icon view.
     *
     * @return the icon view
     */
    public CmisIconView getIconView() {
        return iconView;
    }
    
    /**
     * Gets the thumbnail view.
     *
     * @return the thumbnail view
     */
    public CmisThumbnailView getThumbnailView() {
        return thumbnailView;
    }
    
    /**
     * Traves.
     */
    protected void traves() {
        int index = selectionModel.getMaxSelectionIndex();
        if ( (index>=0) && (dataModel.isTraversable(index)) ) {
            CmisObject file = dataModel.getFile(index);
            selectionModel.setValueIsAdjusting(true);
            dataModel.setCurrentDirectory(file);
            selectionModel.setValueIsAdjusting(false);
            dataModel.refresh();
        }
    }
    
    /* (non-Javadoc)
     * @see javax.swing.JComponent#setTransferHandler(javax.swing.TransferHandler)
     */
    @Override
    public void setTransferHandler(TransferHandler newHandler) {
        detailView.setTransferHandler(newHandler);
        listView.setTransferHandler(newHandler);
        iconView.setTransferHandler(newHandler);
        thumbnailView.setTransferHandler(newHandler);
    }
    
    /**
     * Sets the drag enabled.
     *
     * @param b the new drag enabled
     */
    public void setDragEnabled(boolean b) {
        detailView.setDragEnabled(b);
        listView.setDragEnabled(b);
        iconView.setDragEnabled(b);
        thumbnailView.setDragEnabled(b);
    }
    
    /**
     * Removes the list selection listener.
     *
     * @param l the l
     */
    public void removeListSelectionListener(ListSelectionListener l) {
        selectionModel.removeListSelectionListener(l);
    }
    
    /**
     * Adds the list selection listener.
     *
     * @param l the l
     */
    public void addListSelectionListener(ListSelectionListener l) {
        selectionModel.addListSelectionListener(l);
    }
    
    /**
     * Adds the list data listener.
     *
     * @param l the l
     */
    public void addListDataListener(ListDataListener l) {
        dataModel.addListDataListener(l);
    }
    
    /**
     * Removes the list data listener.
     *
     * @param l the l
     */
    public void removeListDataListener(ListDataListener l) {
        dataModel.removeListDataListener(l);
    }
    
    /**
     * Adds the cell editor listener.
     *
     * @param l the l
     */
    public void addCellEditorListener(CellEditorListener l) {
        detailView.getColumnModel().getColumn(0).getCellEditor().addCellEditorListener(l);
        listView.getCellEditor().addCellEditorListener(l);
        iconView.getCellEditor().addCellEditorListener(l);
        thumbnailView.getCellEditor().addCellEditorListener(l);
    }
    
    /**
     * Removes the cell editor listener.
     *
     * @param l the l
     */
    public void removeCellEditorListener(CellEditorListener l) {
        detailView.getColumnModel().getColumn(0).getCellEditor().removeCellEditorListener(l);
        listView.getCellEditor().removeCellEditorListener(l);
        iconView.getCellEditor().removeCellEditorListener(l);
        thumbnailView.getCellEditor().removeCellEditorListener(l);
    }
    
    /**
     * Edits the cell at.
     *
     * @param index the index
     * @return true, if successful
     */
    public boolean editCellAt(int index) {
        boolean result = false;
        
        dataModel.setState(CmisObjectListViewModel.EDIT);
        switch (viewStyle) {
            case VS_DETAIL:
                result = detailView.editCellAt(index,0);
                break;
            case VS_LIST:
                result = listView.editCellAt(index);
                break;
            case VS_ICON:
                result = iconView.editCellAt(index);
                break;
            case VS_THUMBNAIL:
                result = thumbnailView.editCellAt(index);
                break;
            default:
                result = false;
                break;
        }
        
        return result;
    }
    
    /* (non-Javadoc)
     * @see java.awt.Component#addMouseListener(java.awt.event.MouseListener)
     */
    public void addMouseListener(MouseListener l) {
        detailView.addMouseListener(l);
        listView.addMouseListener(l);
        iconView.addMouseListener(l);
        thumbnailView.addMouseListener(l);
    }
    
    /* (non-Javadoc)
     * @see java.awt.Component#removeMouseListener(java.awt.event.MouseListener)
     */
    public void removeMouseListener(MouseListener l) {
        detailView.removeMouseListener(l);
        listView.removeMouseListener(l);
        iconView.removeMouseListener(l);
        thumbnailView.removeMouseListener(l);
    }
    
    /* (non-Javadoc)
     * @see java.awt.Component#addKeyListener(java.awt.event.KeyListener)
     */
    public void addKeyListener(KeyListener l) {
        detailView.addKeyListener(l);
        listView.addKeyListener(l);
        iconView.addKeyListener(l);
        thumbnailView.addKeyListener(l);
    }
    
    /* (non-Javadoc)
     * @see java.awt.Component#removeKeyListener(java.awt.event.KeyListener)
     */
    public void removeKeyListener(KeyListener l) {
        detailView.removeKeyListener(l);
        listView.removeKeyListener(l);
        iconView.removeKeyListener(l);
        thumbnailView.removeKeyListener(l);
    }
    
    ////////////////////////////////////////////
    // EVENT HANDLER
    ///////////////////////////////////////////
    
    /**
     * On contents changed.
     *
     * @param e the e
     */
    private void onContentsChanged(ListDataEvent e) {
        // changeAll
        if ((e.getIndex0()==CmisObjectListViewModel.ALL_INDEX) &&  (e.getIndex1()==CmisObjectListViewModel.ALL_INDEX) ){
            return;
        }
        
        if (e.getIndex0() != e.getIndex1()) {
            return;
        }
        int index = e.getIndex1();
        if (dataModel.getSize() >= index) {
            selectionModel.setSelectionInterval(index,index);
        }
    }
    
    /**
     * The Class ViewMouseHandler.
     */
    private class ViewMouseHandler extends MouseInputAdapter {
        
        /* (non-Javadoc)
         * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
         */
        @Override
        public void mouseClicked(MouseEvent evt) {
            if (evt.getClickCount() == 2) {
            	// Open Folder
            	traves();
            	
            }
        }
        
    }
    
    /**
     * The Class ViewKeyHandler.
     */
    private class ViewKeyHandler extends KeyAdapter {
        
        /* (non-Javadoc)
         * @see java.awt.event.KeyAdapter#keyPressed(java.awt.event.KeyEvent)
         */
        @Override
        public void keyPressed(KeyEvent evt) {
            if (evt.getKeyCode()==KeyEvent.VK_ENTER) {
                traves();
            }
        }
    }

	/* (non-Javadoc)
	 * @see fr.umlv.cmis.listview.ViewComponent#getViewModel()
	 */
	public CmisObjectListViewModel getViewModel() {
		 return (CmisObjectListViewModel)getModel();
	}

	/* (non-Javadoc)
	 * @see fr.umlv.cmis.listview.ViewComponent#getSelectionModel()
	 */
	public ListSelectionModel getSelectionModel() {
		return selectionModel;
	}

	/* (non-Javadoc)
	 * @see fr.umlv.cmis.listview.ViewComponent#getIconSize()
	 */
	@Override
	public int getIconSize() {
		return ICON_SIZE;
	}
}
